#include "stdafx.h"

#include <iostream>
using namespace std;
#include "rsc_decoder.h"

static const double M_PI   =  3.1415926535897932;

// Construtor da Classe "rsc_decoder"
rsc_decoder::rsc_decoder(rsc_encoder * _encoder,unsigned int _PUNCTURED_BITS,double _SNR)
{

	unsigned int i,j,k;
   double temp;

	encoder=_encoder;
	KC=encoder->get_k();	NC=encoder->get_n();	MC=encoder->get_m();

	ZEROTAIL_SIZE=encoder->get_zerotail_size();
	PUNCTURED_BITS=_PUNCTURED_BITS;

	NP=NC*ZEROTAIL_SIZE;

	K=KC*(ZEROTAIL_SIZE-MC);
	N=(NC*ZEROTAIL_SIZE)-PUNCTURED_BITS;

	SNR=_SNR;

	received_sequence=new double *[N];
	for(i=0;i<N;i++) received_sequence[i]=new double [2];

   for(i=0;i<N;i++)
	 for(j=0;j<2;j++) received_sequence[i][j]=0.0;

	transmited_binary_sequence=new unsigned int [N];

	bit_metric=new double *[2];
	for(i=0;i<2;i++) bit_metric[i]=new double [NP];

	for(i=0;i<2;i++)
	 for(j=0;j<NP;j++) bit_metric[i][j]=0.0;

	word_metric=new double [2]; for(i=0;i<2;i++) word_metric[i]=0;

	bit_metric1=new double *[2];
	for(i=0;i<2;i++) bit_metric1[i]=new double [NP];

	for(i=0;i<2;i++)
	 for(j=0;j<NP;j++) bit_metric1[i][j]=0.0;

	word_metric1=new double [2]; for(i=0;i<2;i++) word_metric1[i]=0;

	decoded_binary_sequence=new unsigned int [N]; for(i=0;i<N;i++) decoded_binary_sequence[i]=0;

	PUNCTUR_MATRIX=new unsigned int [NP];

}






// Construtor da Classe "rsc_decoder"
rsc_decoder::rsc_decoder(rsc_encoder * _encoder,unsigned int _PUNCTURED_BITS)
{

	unsigned int i,j,k;
   double temp;

	encoder=_encoder;
	KC=encoder->get_k();	NC=encoder->get_n();	MC=encoder->get_m();

	ZEROTAIL_SIZE=encoder->get_zerotail_size();
	PUNCTURED_BITS=_PUNCTURED_BITS;

	NP=NC*ZEROTAIL_SIZE;

	K=KC*(ZEROTAIL_SIZE-MC);
	N=(NC*ZEROTAIL_SIZE)-PUNCTURED_BITS;

	//SNR=_SNR;

	received_sequence=new double *[N];
	for(i=0;i<N;i++) received_sequence[i]=new double [2];

   for(i=0;i<N;i++)
	 for(j=0;j<2;j++) received_sequence[i][j]=0.0;

	transmited_binary_sequence=new unsigned int [N];

	bit_metric=new double *[2];
	for(i=0;i<2;i++) bit_metric[i]=new double [NP];

	for(i=0;i<2;i++)
	 for(j=0;j<NP;j++) bit_metric[i][j]=0.0;

	word_metric=new double [2]; for(i=0;i<2;i++) word_metric[i]=0;

	bit_metric1=new double *[2];
	for(i=0;i<2;i++) bit_metric1[i]=new double [NP];

	for(i=0;i<2;i++)
	 for(j=0;j<NP;j++) bit_metric1[i][j]=0.0;

	word_metric1=new double [2]; for(i=0;i<2;i++) word_metric1[i]=0;

	decoded_binary_sequence=new unsigned int [N]; for(i=0;i<N;i++) decoded_binary_sequence[i]=0;

	PUNCTUR_MATRIX=new unsigned int [NP];

}







// Destrutor da Classe "rsc_decoder"
rsc_decoder::~rsc_decoder()
{

	unsigned int i,j;

	for(i=0;i<N;i++) delete [] received_sequence[i]; delete [] received_sequence;

	delete [] transmited_binary_sequence;

   for(i=0;i<2;i++) delete [] bit_metric[i];	delete [] bit_metric;

	delete [] word_metric;

	for(i=0;i<2;i++) delete [] bit_metric1[i]; delete [] bit_metric1;

	delete [] word_metric1;

	delete [] decoded_binary_sequence;

  	delete [] PUNCTUR_MATRIX;
}







void rsc_decoder::print_codeword(void)
{
	unsigned int i,j;

	cout << "\n";

	for(i=0;i<2;i++)
	  { for(j=0;j<N;j++) cout << V[i][j]; cout << "\n"; }
}



void rsc_decoder::set_zerotail_punctur_matrix(unsigned int * _PUNCTUR_MATRIX)
{
	unsigned int i;

	for(i=0;i<NP;i++) PUNCTUR_MATRIX[i]=_PUNCTUR_MATRIX[i];
}







// --------------------  Channel Log_Likelihood_Ratio --------------------------

long double * rsc_decoder::channel_information_log_likelihood_ratio(long double * received)
{
  unsigned int count=0;
  long double * LLR_C=new long double [ZEROTAIL_SIZE];

  for(int i=0;i<ZEROTAIL_SIZE;i++) { LLR_C[i]=4.0*SNR*received[count]; count=count+2; }

  return LLR_C;
}



long double *** rsc_decoder::get_received_sequence(long double * R)
{
  unsigned int i,j,count;
  long double *** LLR_E;

  LLR_E=new long double ** [ZEROTAIL_SIZE];
  for(i=0;i<ZEROTAIL_SIZE;i++) LLR_E[i]=new long double * [NC];

  for(i=0;i<ZEROTAIL_SIZE;i++)
   for(j=0;j<NC;j++) LLR_E[i][j]=new long double [1];

  //cout << "\nEntrei: " << ZEROTAIL_SIZE; cin.get();
  
  count=0;
  for(i=0;i<ZEROTAIL_SIZE;i++)
  {
    //LLR_E[i][0][0]=2.0*SNR*R[count]; LLR_E[i][1][0]=2.0*SNR*R[count+1]; count=count+2;
    //LLR_E[i][0][0]=sqrtl(2.0*SNR)*R[count]; LLR_E[i][1][0]=sqrtl(2.0*SNR)*R[count+1]; count=count+2;
    LLR_E[i][0][0]=R[count]; LLR_E[i][1][0]=R[count+1];
    //cout << "\n" << i << "\t" << count << "\t" << (count+1) << "\t" << LLR_E[i][0][0] << "\t" << LLR_E[i][1][0]; cin.get();
    count=count+2;
  }

  //cout << "\nSai: " << ZEROTAIL_SIZE; cin.get();

  return LLR_E;
}






long double *** rsc_decoder::log_probability_density_function(long double * R)
{
  int i,j,k,count;

  long double *** LLR_E;

  LLR_E=new long double ** [ZEROTAIL_SIZE];
  for(i=0;i<ZEROTAIL_SIZE;i++) LLR_E[i]=new long double * [NC];

  for(i=0;i<ZEROTAIL_SIZE;i++)
   for(j=0;j<NC;j++) LLR_E[i][j]=new long double [2];

  for(i=0;i<N;i++)
   {
    bit_metric[1][i]=(0.5*logl(SNR/M_PI))-SNR*powl((R[i]-1.0),2.0);
    bit_metric[0][i]=(0.5*logl(SNR/M_PI))-SNR*powl((R[i]+1.0),2.0);

    //cout << "\n" << bit_metric[0][i] << "  " << bit_metric[1][i]; cin.get();
   }

  count=0;
  for(i=0;i<ZEROTAIL_SIZE;i++)
   {
     LLR_E[i][0][0]=bit_metric[0][count];   LLR_E[i][0][1]=bit_metric[1][count];
     LLR_E[i][1][0]=bit_metric[0][count+1]; LLR_E[i][1][1]=bit_metric[1][count+1];
	  count=count+2;
   }

return LLR_E;
}





long double *** rsc_decoder::log_probability_density_function_2(long double * R,long double * Z,long double mz,long double sigmaz)
{
  unsigned int i,j,k,count;
  long double *** LLR_E;

  LLR_E=new long double ** [ZEROTAIL_SIZE];
  for(i=0;i<ZEROTAIL_SIZE;i++) LLR_E[i]=new long double * [3];

  for(i=0;i<ZEROTAIL_SIZE;i++)
   for(j=0;j<3;j++) LLR_E[i][j]=new long double [2];

  for(i=0;i<N;i++)
   {
     bit_metric[1][i]=(0.5*logl(SNR/M_PI))-SNR*powl((R[i]-1.0),2.0);
     bit_metric[0][i]=(0.5*logl(SNR/M_PI))-SNR*powl((R[i]+1.0),2.0);
   }

  count=0;
  for(i=0;i<ZEROTAIL_SIZE;i++)
   {
     LLR_E[i][0][0]=bit_metric[0][count];   LLR_E[i][0][1]=bit_metric[1][count];
     LLR_E[i][1][0]=bit_metric[0][count+1]; LLR_E[i][1][1]=bit_metric[1][count+1];

     //LLR_E[i][2][1]=((0.5*logl(1.0/(2.0*M_PI*sigmaz)))-0.5*(powl((Z[i]-mz),2.0)/sigmaz));
     //LLR_E[i][2][0]=((0.5*logl(1.0/(2.0*M_PI*sigmaz)))-0.5*(powl((Z[i]+mz),2.0)/sigmaz));

     LLR_E[i][2][1]=((0.5*logl(1.0/(2.0*M_PI*sigmaz)))-0.5*(powl((Z[i]-1),2.0)/sigmaz));
     LLR_E[i][2][0]=((0.5*logl(1.0/(2.0*M_PI*sigmaz)))-0.5*(powl((Z[i]+1),2.0)/sigmaz));

	  count=count+2;
   }

return LLR_E;
}



long double *** rsc_decoder::decode_zerotail_sequence_2(long double * received)
{
  int i,j,k,count;

  long double s0,s1,A1;
  long double *** metrics;

  metrics=new long double ** [ZEROTAIL_SIZE];
  for(i=0;i<ZEROTAIL_SIZE;i++) metrics[i]=new long double * [NC];

  for(i=0;i<ZEROTAIL_SIZE;i++)
   for(j=0;j<NC;j++) metrics[i][j]=new long double [2];

  for(i=0;i<N;i++)
   {
    s0=expl(-SNR*powl((received[i]-1.0),2.0)); bit_metric[1][i]=sqrtl(SNR/M_PI)*s0;
    s1=expl(-SNR*powl((received[i]+1.0),2.0)); bit_metric[0][i]=sqrtl(SNR/M_PI)*s1;

    //cout << "\n" << logl(bit_metric[0][i]) << "  " << logl(bit_metric[1][i]) << "   " << log(bit_metric[1][i]/bit_metric[0][i]); cin.get();
    //cout << "\n" << received[i] << "  " << log(bit_metric[1][i]/bit_metric[0][i]); cin.get();
   }

  count=0;
  for(i=0;i<ZEROTAIL_SIZE;i++)
   for(j=0;j<NC;j++)
    {
      metrics[i][j][0]=bit_metric[0][count];
	   metrics[i][j][1]=bit_metric[1][count];
	   count++;
    }

return (metrics);
}









void rsc_decoder::print_decoded_sequence(void)
{
	unsigned int i;

	cout << "\n";
	for(i=0;i<N;i++) cout << decoded_binary_sequence[i];

}



unsigned int * rsc_decoder::convert_decimal_binary(unsigned int decimal,unsigned int size)
{
	int e,i,h;
	float a;
	unsigned int * r,* r1,* binary_word,conta=0;

e=0;

if (decimal==0)
	h=1;
else
	{  a=(log((double)decimal)/log((double)2))+1;
		h=(unsigned int) floor(a);
	}

r=new unsigned int [h];
r1=new unsigned int [h];

binary_word=new unsigned int [size];

for(i=0;i<size;i++) binary_word[i]=0;

for (i=0;i<h;i++)	r[i]=0;

for (i=0;i<h;i++)	r1[i]=0;

do
{

if (decimal>(unsigned int) floor(ldexp((double)1,(double)e))) e++;
	else  if (decimal==(unsigned int) floor(ldexp((double)1,(double)e)))
			{
				r[e]=1;
				decimal=0;
			}
			else
			{
			  if (e>0)
				{ e--;
				  r[e]=1;
				  decimal=(decimal-(unsigned int) floor(ldexp((double)1,(double)e)));
				  e=0; }
			}

} while (decimal>0);



for (i=(h-1);i>=0;i--) { r1[conta]=r[i]; conta++; }

for (i=0;i<h;i++) binary_word[size-h+i]=r1[i];

delete [] r; delete [] r1;

return (binary_word);
}








